package com.fadadianqi.logistics.admin.controller;

import com.fadadianqi.logistics.admin.controller.SellController.BillVO.BillVOItem;
import com.fadadianqi.logistics.admin.controller.form.AjaxResult;
import com.fadadianqi.logistics.admin.controller.form.SellForm;
import com.fadadianqi.commons.BackToURLUtils;
import com.fadadianqi.commons.JSONProvider;
import com.fadadianqi.commons.ParamHelper;
import com.fadadianqi.logistics.customer.model.Customer;
import com.fadadianqi.logistics.customer.model.Town;
import com.fadadianqi.logistics.customer.model.Village;
import com.fadadianqi.logistics.customer.service.CustomerService;
import com.fadadianqi.goods.model.Brand;
import com.fadadianqi.goods.model.Category;
import com.fadadianqi.goods.model.Goods;
import com.fadadianqi.goods.model.GoodsPropValue;
import com.fadadianqi.goods.service.GoodsService;
import com.fadadianqi.logistics.inventory.model.Storehouse;
import com.fadadianqi.logistics.inventory.service.InventoryService;
import com.fadadianqi.logistics.inventory.service.StorehouseService;
import com.fadadianqi.logistics.search.GoodsSearcher;
import com.fadadianqi.logistics.search.SellIndexService;
import com.fadadianqi.logistics.search.SellSearcher;
import com.fadadianqi.logistics.search.VillageSearcher;
import com.fadadianqi.search.*;
import com.fadadianqi.logistics.sell.model.Bill;
import com.fadadianqi.logistics.sell.model.Item;
import com.fadadianqi.logistics.sell.service.BillService;
import com.fadadianqi.logistics.sell.service.InOutService;
import com.yeqiangwei.commons.util.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.search.NumericRangeQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.support.SessionStatus;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Controller
public class SellController {

    private static final Log log = LogFactory.getLog(SellController.class);
    private static final String VIEW_LIST = "admin/sell/list";
    private static final String VIEW_FORM = "admin/sell/form";
    private static final String COMMAND_NAME = "sellForm";
    private static final int MAX_LIST_RESULTS = 20; // 每页显示的最多条数

    private static final String PARAM_BACK_URL = "backURL";

    @RequestMapping(value = "/a/ajax/sell/villageList", method = RequestMethod.GET)
    public String ajaxVillageList(ModelMap modelMap) {
        modelMap.put("villageVOList", allVillageList());
        return "admin/sell/villageList";
    }

    @RequestMapping(URIMappingUtils.INVENTORY_PREFIX + "/ajax/sell/villageFilter")
    public String villageFilter(HttpServletRequest request, ModelMap modelMap)
            throws Exception {
        String q = ParamUtils.getString(request, "q", null);
        if (q == null) {
            modelMap.put("villageVOList", allVillageList());
        } else {
            modelMap.put("villageVOList", searchVillage(request, q));
        }
        return "/admin/sell/villageFilter";
    }

    private List<VillageVOArray> searchVillage(HttpServletRequest request, String q) throws Exception {
        Pagination pagination = new Pagination(request, 300);
        Result result = villageSearcher.search(q, pagination);
        Map<String, VillageVOArray> voMap = new HashMap<String, VillageVOArray>();
        if (result != null && result.getItems() != null) {
            List<?> list = result.getItems();
            for (Object o : list) {
                VillageSearcher.VillageVO v = (VillageSearcher.VillageVO) o;
                VillageVOArray vo = voMap.get(v.getTownId());
                if (vo == null) {
                    vo = new VillageVOArray();
                    vo.setVillageList(new ArrayList<Village>());
                }
                vo.setTown(customerService.getTownById(v.getTownId()));
                vo.getVillageList().add(v);
                voMap.put(v.getTownId(), vo);
            }
        }
        return new ArrayList<VillageVOArray>(voMap.values());
    }

    private List<VillageVOArray> allVillageList() {
        List<Town> townList = customerService.findAllTown();
        List<VillageVOArray> voList = new ArrayList<VillageVOArray>();
        for (Town town : townList) {
            VillageVOArray vo = new VillageVOArray();
            vo.setTown(town);
            List<Village> villageList = customerService.findAllVillage(town.getId());
            vo.setVillageList(villageList);
            voList.add(vo);
        }
        return voList;
    }

    @RequestMapping(URIMappingUtils.INVENTORY_PREFIX + "/sell/search")
    public String search(HttpServletRequest request, ModelMap modelMap)
            throws Exception {
        BackToURLUtils.setCurrentURLToAttr(request, PARAM_BACK_URL);


        String s = ParamUtils.getString(request, "s", null);
        String e = ParamUtils.getString(request, "e", null);
        String q = ParamUtils.getString(request, "q", null);
        if (q == null) {
            return showList(request, modelMap);
        }
        modelMap.put("q", q);
        Pagination pagination = new Pagination(request, MAX_LIST_RESULTS);
        Result result = null;
        Long min;
        Long max;
        Sort sort = new Sort(new SortField(SellIndexService.FIELD_ADD_TIME, SortField.LONG, true));
        if (s != null) {
            String start = s + " 00:00:00";
            String end = null;
            if (e != null) {
                end = e + " 23:59:59";
            }
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            min = sdf.parse(start).getTime();
            if (end != null) {
                max = sdf.parse(end).getTime();
            } else {
                max = DateTimeUtils.now();
            }
            Query rangeQuery = NumericRangeQuery.newLongRange(SellIndexService.FIELD_ADD_TIME, min, max, Boolean.TRUE, Boolean.TRUE);
            result = sellSearcher.search(q, rangeQuery, sort, pagination);
        } else {
            result = sellSearcher.search(q, null, sort, pagination);
        }
        log.info("#search# keywords is: " + q);
        List<?> list = result.getItems();
        pagination.setTotal(result.getTotal());
        log.info("#search# keywords is: " + q + ", total: " + result.getTotal());
        Map<String, Object> elements = new HashMap<String, Object>();
        elements.put("q", q);
        elements.put("s", s);
        elements.put("e", e);
        pagination.setElements(elements);
        PaginationHelper.setAttribute(request, pagination);
        List<BillVO> voList = new ArrayList<BillVO>();
        if (ValidatorHelper.isNotEmpty(list)) {
            for (int i = 0; i < list.size(); i++) {
                Bill bill = (Bill) list.get(i);
                String billId = bill.getId();
                BillVO vo = new BillVO();
                vo.setId(billId);
                List<BillVO.BillVOItem> voItemList = new ArrayList<BillVO.BillVOItem>();
                this.voItemListBuilder(voItemList, bill);
                BeanUtils.copyProperties(vo, bill);
                String customerId = bill.getCustomerId();
                Customer customer = customerService.getById(customerId);
                if (customer != null) {
                    vo.setCustomer(customer);

                    String townId = customer.getTownId();
                    Town town = customerService.getTownById(townId);
                    vo.setTown(town);

                    String villageId = customer.getVillageId();
                    Village village = customerService.getVillageById(villageId);
                    vo.setVillage(village);
                }
                vo.setItemList(voItemList);
                voList.add(vo);
            }
        }

        modelMap.put("billVOList", voList);
        /*List<Category> categoryList = goodsService.findAllCategory();
        modelMap.put("categoryList", categoryList);
        List<Brand> brandList = goodsService.findAllBrand();
        modelMap.put("brandList", brandList);*/
        return VIEW_LIST;
    }

    @RequestMapping(URIMappingUtils.INVENTORY_PREFIX
            + "/ajax/sell/goods_{brandId}_{categoryId}")
    public String ajaxShowGoods(@PathVariable String brandId,
                                @PathVariable String categoryId, ModelMap modelMap) {
        if (log.isDebugEnabled()) {
            log.debug("#ajaxShowGoods# brandId: " + brandId + ", categoryId: "
                    + categoryId);
        }

        Brand brand = goodsService.getBrandById(brandId);

        Category category = goodsService.getCategoryById(categoryId);

        List<Goods> goodsList = goodsService.findByBrandIdAndCategoryId(brandId, categoryId, null);

        if (ValidatorHelper.isNotEmpty(categoryId)) {
            List<?> props = goodsService.findPropsByCategoryId(categoryId);
            modelMap.put("props", props);
        }

        List<GoodsVO> voList = new ArrayList<SellController.GoodsVO>();
        for (Goods goods : goodsList) {
            GoodsVO vo = new GoodsVO();
            BeanUtils.copyProperties(vo, goods);
            vo.setBrand(brand);
            vo.setCategory(category);
            vo.setPropValues(goodsService.findGoodsPropValueByGoodsId(vo.getId()));
            vo.setInventoryCount(inventoryService.countStatusNormalByGoodsId(goods.getId()));
            voList.add(vo);
        }
        modelMap.put("goodsVOList", voList);

        return "admin/sell/goodsList";
    }

    @RequestMapping(URIMappingUtils.INVENTORY_PREFIX + "/ajax/sell/brand")
    public String showBrand(HttpServletRequest request, ModelMap modelMap) {
        String letterBrand = ParamUtils.getString(request, "letterBrand", null);
        List<Brand> _brandList = goodsService.findAllBrand();
        if (null == letterBrand) {
            modelMap.put("brandList", _brandList);
        } else {
            List<Brand> brandList = new ArrayList<Brand>();
            for (Brand brand : _brandList) {
                String initial = StringHelper.getInitial(brand.getName(), null);
                if (initial == null) {
                    continue;
                }
                String letter = StringHelper.substring(initial, 0, 1, initial);
                if (letterBrand.equalsIgnoreCase(letter)) {
                    brandList.add(brand);
                }
                modelMap.put("brandList", brandList);
            }
        }
        return "/admin/sell/brand";
    }

    @RequestMapping(URIMappingUtils.INVENTORY_PREFIX + "/ajax/sell/category")
    public String showCategory(HttpServletRequest request, ModelMap modelMap) {
        String letterCategory = ParamUtils.getString(request, "letterCategory", null);
        List<Category> categoryList = new ArrayList<Category>();
        List<Category> _categoryList = goodsService.findAllCategory();
        if (null == letterCategory) {
            modelMap.put("categoryList", _categoryList);
        } else {
            for (Category category : _categoryList) {
                String initial = StringHelper.getInitial(category.getName(), null);
                if (initial == null) {
                    continue;
                }
                String letter = StringHelper.substring(initial, 0, 1, initial);
                if (letterCategory.equalsIgnoreCase(letter)) {
                    categoryList.add(category);
                }
                modelMap.put("categoryList", categoryList);
            }
        }
        return "/admin/sell/category";
    }

    @RequestMapping(URIMappingUtils.INVENTORY_PREFIX + "/ajax/sell/goodsSelector")
    public String showBrandAndCategory(HttpServletRequest request,
                                       ModelMap modelMap) {

        List<Category> categoryList = goodsService.findAllCategory();
        modelMap.put("categoryList", categoryList);

        List<Brand> brandList = goodsService.findAllBrand();
        modelMap.put("brandList", brandList);

        List<GoodsVO> voList = new ArrayList<SellController.GoodsVO>();
        String q = ParamUtils.getString(request, "q", null);
        String cid = ParamUtils.getString(request, "cid", null);
        String bid = ParamUtils.getString(request, "bid", null);
        if (ValidatorHelper.isEmpty(q)
                && ValidatorHelper.isEmpty(cid)
                && ValidatorHelper.isEmpty(bid)) {
            return "/admin/sell/brandAndCategory";
        } else if (ValidatorHelper.isNotEmpty(cid) || ValidatorHelper.isNotEmpty(bid)) {
            // 按照品牌和种类找商品
            Brand brand = goodsService.getBrandById(bid);
            Category category = goodsService.getCategoryById(cid);
            List<Goods> goodsList = goodsService.findByBrandIdAndCategoryId(bid, cid, null);
            for (Goods goods : goodsList) {
                GoodsVO vo = new GoodsVO();
                BeanUtils.copyProperties(vo, goods);
                vo.setBrand(brand);
                vo.setCategory(category);
                vo.setPropValues(goodsService.findGoodsPropValueByGoodsId(vo.getId()));
                vo.setInventoryCount(inventoryService.countStatusNormalByGoodsId(goods.getId()));
                voList.add(vo);
            }
        } else {
            // 按关键词查找商品
            Pagination pagination = new Pagination(request, 100);
            try {
                Result result = goodsSearcher.search(q, pagination);
                pagination.setTotal(result.getTotal());
                if (result != null && result.getItems() != null) {
                    List<?> list = result.getItems();
                    for (Object rs : list) {
                        GoodsSearcher.GoodsVO g = (GoodsSearcher.GoodsVO) rs;
                        Goods goods = goodsService.getGoodsById(g.getId());
                        GoodsVO vo = new GoodsVO();
                        BeanUtils.copyProperties(vo, goods);
                        vo.setBrand(goodsService.getBrandById(goods.getBrandId()));
                        vo.setCategory(goodsService.getCategoryById(goods.getCategoryId()));
                        vo.setInventoryCount(inventoryService.countStatusNormalByGoodsId(goods.getId()));
                        vo.setPropValues(goodsService.findGoodsPropValueByGoodsId(goods.getId()));
                        voList.add(vo);
                    }
                }
            } catch (Exception e) {
                log.error(e.toString());
            }
        }
        modelMap.put("goodsVOList", voList);
        return "/admin/sell/goodsList";
    }

    @RequestMapping(URIMappingUtils.INVENTORY_PREFIX + "/ajax/sell/goods-{id}")
    @ResponseBody
    public ResponseEntity<String> ajaxGetGoods(@PathVariable String id) {
        HttpHeaders responseHeaders = new HttpHeaders();
        responseHeaders.add("Content-Type", "text/html; charset=utf-8");

        Goods goods = goodsService.getGoodsById(id);
        GoodsVO vo = new GoodsVO();
        BeanUtils.copyProperties(vo, goods);

        Brand brand = goodsService.getBrandById(goods.getBrandId());
        vo.setBrand(brand);

        Category category = goodsService.getCategoryById(goods.getCategoryId());
        vo.setCategory(category);

        vo.setInventoryCount(inventoryService.countStatusNormalByGoodsId(goods.getId()));

        AjaxResult rs = new AjaxResult(vo, Boolean.TRUE, null);
        return new ResponseEntity<String>(JSONProvider.toJSON(rs),
                responseHeaders, HttpStatus.OK);
    }

    @RequestMapping(URIMappingUtils.INVENTORY_PREFIX + "/ajax/sell/sellItem")
    public String ajaxSellItem(HttpServletRequest request,
                               ModelMap modelMap) {
        String id = ParamUtils.getString(request, "id", null);
        Goods goods = goodsService.getGoodsById(id);
        Brand brand = goodsService.getBrandById(goods.getBrandId());
        Category category = goodsService.getCategoryById(goods.getCategoryId());
        int count = inventoryService.countStatusNormalByGoodsId(id);
        modelMap.put("goods", goods);
        modelMap.put("brand", brand);
        modelMap.put("category", category);
        modelMap.put("count", count);
        modelMap.put("propValues", goodsService.findGoodsPropValueByGoodsId(goods.getId()));
        return "/admin/sell/sellItem";
    }

    @RequestMapping(URIMappingUtils.INVENTORY_PREFIX
            + "/ajax/sell/village-{id}")
    @ResponseBody
    public ResponseEntity<String> ajaxGetVillage(@PathVariable String id) {
        HttpHeaders responseHeaders = new HttpHeaders();
        responseHeaders.add("Content-Type", "text/html; charset=utf-8");
        VillageVO vo = new VillageVO();
        Village village = customerService.getVillageById(id);
        BeanUtils.copyProperties(vo, village);
        Town town = customerService.getTownById(village.getTownId());
        vo.setTown(town);
        vo.setVillage(village);
        AjaxResult rs = new AjaxResult(vo, Boolean.TRUE, null);
        return new ResponseEntity<String>(JSONProvider.toJSON(rs),
                responseHeaders, HttpStatus.OK);
    }

    @RequestMapping("/a/ajax/sell/print")
    @ResponseBody
    public ResponseEntity<String> printBill(HttpServletRequest request,
                                            ModelMap modelMap) {
        String billId = ParamHelper.getBillId(request, null);
        boolean printUnit = ParamUtils.getBoolean(request, "unit", false);
        Boolean succeed;
        try {
            billService.print(billId, printUnit);
            succeed = Boolean.TRUE;
        } catch (Exception e) {
            e.printStackTrace();
            succeed = Boolean.FALSE;
        }
        AjaxResult rs = new AjaxResult(null, succeed, null);
        HttpHeaders responseHeaders = new HttpHeaders();
        responseHeaders.add("Content-Type", "text/html; charset=utf-8");
        return new ResponseEntity<String>(rs.toJSON(), responseHeaders,
                HttpStatus.OK);
    }

    @RequestMapping(URIMappingUtils.INVENTORY_PREFIX + "/sell/list")
    public String showList(HttpServletRequest request, ModelMap modelMap)
            throws ParseException {

        BackToURLUtils.setCurrentURLToAttr(request, PARAM_BACK_URL);

        Map<String, Object> params = new HashMap<String, Object>();
        Pagination pagination = new Pagination(request, MAX_LIST_RESULTS);
        pagination.setOrderList(new Pagination.Order[]{
                Pagination.getNewOrder("add_time", Pagination.Order.DESCENDING)});
        List<Bill> list = null;

        String s = null;
        String e = null;

        String day = ParamUtils.getString(request, "d", null);
        if (ValidatorHelper.isNotEmpty(day)) {
            if (day.equalsIgnoreCase("today")) {
                s = DateTimeUtils.format(new Date().getTime(), DateTimeUtils.FMT_YYYY_MM_DD);
                e = DateTimeUtils.format(new Date().getTime(), DateTimeUtils.FMT_YYYY_MM_DD);
            } else if (day.equalsIgnoreCase("yestoday")) {
                s = DateTimeUtils.format(DateTimeUtils.nDaysAfterTime(-1), DateTimeUtils.FMT_YYYY_MM_DD);
                e = DateTimeUtils.format(DateTimeUtils.nDaysAfterTime(-1), DateTimeUtils.FMT_YYYY_MM_DD);
            } else if (day.equalsIgnoreCase("bfyestoday")) {
                s = DateTimeUtils.format(DateTimeUtils.nDaysAfterTime(-2), DateTimeUtils.FMT_YYYY_MM_DD);
                e = DateTimeUtils.format(DateTimeUtils.nDaysAfterTime(-2), DateTimeUtils.FMT_YYYY_MM_DD);
            } else if (day.equalsIgnoreCase("week")) {
                s = DateTimeUtils.format(DateTimeUtils.getFirstDayOfWeek(null), DateTimeUtils.FMT_YYYY_MM_DD);
                e = DateTimeUtils.format(DateTimeUtils.getLastDayOfWeek(null), DateTimeUtils.FMT_YYYY_MM_DD);
            } else if (day.equalsIgnoreCase("month")) {
                s = DateTimeUtils.format(DateTimeUtils.getFirstDayOfMonth(), DateTimeUtils.FMT_YYYY_MM_DD);
                e = DateTimeUtils.format(DateTimeUtils.getLastDayOfMonth(), DateTimeUtils.FMT_YYYY_MM_DD);
            }
            params.put("d", day);
            modelMap.put("d", day);
        } else {
            s = ParamUtils.getString(request, "s", null);
            e = ParamUtils.getString(request, "e", null);
        }

        String vid = ParamUtils.getString(request, "vid", null);
        String tid = ParamUtils.getString(request, "tid", null);
        String cid = ParamUtils.getString(request, "cid", null);
        Boolean isReturn = ParamUtils.getBoolean(request, "irn", null);
        Boolean isChecked = ParamUtils.getBoolean(request, "ick", null);
        if (log.isDebugEnabled()) {
            log.debug("s: " + s);
            log.debug("e: " + e);
        }
        int total = 0;
        if (s != null && e != null) {

            String start = s + " 00:00:00";
            String end = e + " 23:59:59";

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date date1 = sdf.parse(start);
            Date date2 = sdf.parse(end);
            list = billService.between(date1, date2, pagination);
            modelMap.put("sumPurchase", billService.sumPurchaseBetween(date1, date2));
            modelMap.put("sumCost", billService.sumCostBetween(date1, date2));
            modelMap.put("sumRealPayables", billService.sumRealPayablesBetween(date1, date2));
            modelMap.put("inOutMoney", inOutService.sumMoneyBetween(date1, date2));
            params.put("s", s);
            params.put("e", e);
            total = billService.countBetween(date1, date2);
        } else if (vid != null) {
            list = billService.findByVillageId(vid, pagination);
            total = billService.countByVillageId(vid);
        } else if (tid != null) {
            list = billService.findByTownId(tid, pagination);
            total = billService.countByTownId(tid);
        } else if (cid != null) {
            list = billService.findByCustomerId(cid, pagination);
            total = billService.countByCustomerId(cid);
        } else if (isReturn != null) {
            list = billService.findAllWithIsReturn(isReturn, pagination);
            total = billService.countAllWithIsReturn(isReturn);
            modelMap.put("irn", isReturn);
        } else if (isChecked != null) {
            list = billService.findAllWithIsChecked(isChecked, pagination);
            total = billService.countAllWithIsChecked(isChecked);
            modelMap.put("ick", isChecked);
        } else {
            list = billService.findAll(pagination);
            total = billService.countAll();
        }

        pagination.setElements(params);
        pagination.setTotal(total);
        PaginationHelper.setAttribute(request, pagination);

        if (day == null) {
            modelMap.put("s", s);
            modelMap.put("e", e);
        }

        List<BillVO> voList = new ArrayList<BillVO>();
        if (ValidatorHelper.isNotEmpty(list)) {
            for (Bill bill : list) {
                BillVO vo = new BillVO();
                vo.setId(bill.getId());
                List<BillVO.BillVOItem> voItemList = new ArrayList<BillVO.BillVOItem>();
                this.voItemListBuilder(voItemList, bill);
                BeanUtils.copyProperties(vo, bill);
                String customerId = bill.getCustomerId();
                Customer customer = customerService.getById(customerId);
                if (customer != null) {
                    vo.setCustomer(customer);
                    String townId = customer.getTownId();
                    Town town = customerService.getTownById(townId);
                    vo.setTown(town);

                    String _villageId = customer.getVillageId();
                    Village village = customerService.getVillageById(_villageId);
                    vo.setVillage(village);
                }
                vo.setItemList(voItemList);
                voList.add(vo);
            }
        }

        modelMap.put("billVOList", voList);

        /*List<Category> categoryList = goodsService.findAllCategory();
        modelMap.put("categoryList", categoryList);

        List<Brand> brandList = goodsService.findAllBrand();
        modelMap.put("brandList", brandList);*/

        return VIEW_LIST;
    }

    private void voItemListBuilder(List<BillVOItem> voItemList, Bill bill) {
        String billId = bill.getId();

        List<com.fadadianqi.logistics.sell.model.Goods> goodsList = billService.findGoodsByBillId(billId);
        if (ValidatorHelper.isNotEmpty(goodsList)) {
            for (com.fadadianqi.logistics.sell.model.Goods billGoods : goodsList) {
                BillVOItem voItem = new BillVOItem();
                voItem.setBillId(bill.getId());

                Goods goods = goodsService.getGoodsById(billGoods.getGoodsId());
                voItem.setGoods(goods);

                Brand brand = goodsService.getBrandById(goods.getBrandId());
                voItem.setBrand(brand);

                Category category = goodsService.getCategoryById(goods.getCategoryId());
                voItem.setCategory(category);

                voItem.setPayables(billGoods.getUnitPrice());
                voItem.setNumber(billGoods.getNumber());

                voItemList.add(voItem);
            }
        } else {
            List<Item> itemList = billService.findItemsByBillId(billId);
            for (Item item : itemList) {

                BillVOItem voItem = new BillVOItem();
                voItem.setIsReturn(item.getIsReturn());
                voItem.setBillId(billId);

                Goods goods = goodsService.getGoodsById(item.getGoodsId());
                voItem.setGoods(goods);

                Brand brand = goodsService.getBrandById(goods.getBrandId());
                voItem.setBrand(brand);

                String categoryId = goods.getCategoryId();

                Category category = goodsService.getCategoryById(categoryId);
                voItem.setCategory(category);

                voItem.setPayables(item.getPayables());
                voItem.setNumber(1);
                voItemList.add(voItem);
            }
        }
    }

    @RequestMapping(value = URIMappingUtils.INVENTORY_PREFIX + "/sell/form", method = RequestMethod.GET)
    public String showForm(HttpServletRequest request, Model model) {
        model.addAttribute(COMMAND_NAME, new SellForm());
        String sgid = ParamUtils.getString(request, "sgid", null);
        if (sgid != null) {
            model.addAttribute("billForm", formBuilder(sgid));
            List<SellItemForm> sellItemList = new ArrayList<SellItemForm>();
            sellItemList.add(sellItemBuilder(sgid));
            model.addAttribute("sellItemList", sellItemList);
        }

        model.addAttribute("goodsId", getGoodsIdBuf(request));

        BackToURLUtils.setParamURLToAttr(request, PARAM_BACK_URL);

        String needPrint = HttpCookieUtils.getValue(request, "needPrint", "true");
        model.addAttribute("needPrint", needPrint);
        return VIEW_FORM;
    }

    private String getGoodsIdBuf(HttpServletRequest request) {
        return HttpCookieUtils.getValue(request, "goodsIdBuf", null);
    }

	/*
     * private void saveGoodsIdBuf(HttpServletRequest request ,
	 * HttpServletResponse response, String goodsId) {
	 * HttpCookieUtils.setValue(response, null, "goodsIdBuf", goodsId, 1); }
	 */

    private SellItemForm sellItemBuilder(String goodsId) {
        if (ValidatorHelper.isNotEmpty(goodsId)) {
            return null;
        }
        SellItemForm form = new SellItemForm();
        Goods goods = goodsService.getGoodsById(goodsId);
        form.setGoods(goods);
        form.setBrand(goodsService.getBrandById(goods.getBrandId()));
        form.setCategory(goodsService.getCategoryById(goods.getCategoryId()));
        return form;
    }

    private BillForm formBuilder(String goodsId) {
        BillForm form = new BillForm();
        form.setPayables(0D);
        form.setRealPayables(0D);
        form.setBillId(null);
        String customerName = null;
        form.setCustomerName(customerName);

        String villageId = null;
        form.setVillageId(villageId);

        BillFormItem formItem = new BillFormItem();
        formItem.setGoodsId(goodsId);
        formItem.setPayables(0D);

        List<BillFormItem> itemList = new ArrayList<BillFormItem>();
        itemList.add(formItem);
        form.setItemList(itemList);
        return form;
    }

    @RequestMapping(value = URIMappingUtils.INVENTORY_PREFIX + "/sell/save", method = RequestMethod.POST)
    public String save(@ModelAttribute(COMMAND_NAME) SellForm form,
                       BindingResult result, SessionStatus status) {
        // TODO validate form
        if (result.hasErrors()) {
            return VIEW_FORM;
        }

        status.setComplete();
        return VIEW_FORM;
    }

    /**
     * @return
     */
    @RequestMapping(value = "/a/sell/save-bill", method = RequestMethod.POST)
    public ResponseEntity<String> saveBill(HttpServletRequest request,
                                           HttpServletResponse response, ModelMap modelMap) {
        HttpHeaders responseHeaders = new HttpHeaders();
        responseHeaders.add("Content-Type", "text/html; charset=utf-8");
        String json = ParamUtils.getString(request, "json", null);

        if (log.isDebugEnabled()) {
            log.debug("json: " + json);
        }

        Object JSON = JSONProvider.toBean(json, BillForm.class);

        AjaxResult rs = null;

        if (JSON == null) {
            String msg = messageSource.getMessage("remind.illegal.parameters", null, Locale.getDefault());
            rs = new AjaxResult(null, Boolean.FALSE, msg);
        } else {
            BillForm form = (BillForm) JSON;
            try {
                billService.saveBill(form);
                rs = new AjaxResult(form, Boolean.TRUE, null);
                HttpCookieUtils.setValue(response, null, "needPrint", form.getNeedPrint(), 365 * 1000);
            } catch (Exception e) {
                String msg = messageSource.getMessage("remind.error", null, Locale.getDefault());
                rs = new AjaxResult(form, Boolean.FALSE, msg);
                log.error(e.toString());
            }
        }

        return new ResponseEntity<String>(JSONProvider.toJSON(rs),
                responseHeaders, HttpStatus.OK);
    }

    @RequestMapping("/a/ajax/sell/choose-storehouse")
    public String chooseStorehouse(HttpServletRequest request, ModelMap modelMap) {
        String gid = ParamHelper.getGoodsId(request, null);
        Goods goods = goodsService.getGoodsById(gid);
        List<Storehouse> list = storehouseService.findAll();
        List<StorehouseVO> storehouseList = new ArrayList<StorehouseVO>();
        int noneTotal = storehouseService.countGoods(goods, null);
        int total = noneTotal;
        if (ValidatorHelper.isNotEmpty(list)) {
            for (Storehouse sh : list) {
                StorehouseVO vo = new StorehouseVO();
                BeanUtils.copyProperties(vo, sh);
                vo.setCount(storehouseService.countGoods(goods, sh));
                storehouseList.add(vo);
                total += vo.getCount();
            }
        }
        modelMap.put("noneTotal", noneTotal);
        modelMap.put("storehouseList", storehouseList);
        modelMap.put("total", total);
        modelMap.put("gid", gid);
        return "/admin/sell/chooseStorehouse";
    }

    @Autowired
    private StorehouseService storehouseService;

    @Autowired
    private VillageSearcher villageSearcher;
    @Autowired
    private GoodsSearcher goodsSearcher;
    @Autowired
    private InOutService inOutService;

    @Autowired
    private MessageSource messageSource;

    @Autowired
    private BillService billService;

    @Autowired
    private CustomerService customerService;

    @Autowired
    private GoodsService goodsService;

    @Autowired
    private InventoryService inventoryService;

    @Autowired
    private SellSearcher sellSearcher;

    public static class StorehouseVO extends Storehouse {

        /**
         *
         */
        private static final long serialVersionUID = -2523594187695826201L;

        private int count;

        public int getCount() {
            return count;
        }

        public void setCount(int count) {
            this.count = count;
        }
    }

    public static class SellItemForm {

        private Brand brand;
        private Category category;
        private Goods goods;

        public Brand getBrand() {
            return brand;
        }

        public void setBrand(Brand brand) {
            this.brand = brand;
        }

        public Category getCategory() {
            return category;
        }

        public void setCategory(Category category) {
            this.category = category;
        }

        public Goods getGoods() {
            return goods;
        }

        public void setGoods(Goods goods) {
            this.goods = goods;
        }
    }

    public static class BillForm {

        private String billId;
        private String customerName;
        private String villageId;
        private Double payables;
        private Double realPayables;
        private List<BillFormItem> itemList;
        private Boolean needPrint;
        private Boolean needPrintUnitPrice;
        private String mobile;
        private String memo;

        public Boolean getNeedPrintUnitPrice() {
            return needPrintUnitPrice;
        }

        public void setNeedPrintUnitPrice(Boolean needPrintUnitPrice) {
            this.needPrintUnitPrice = needPrintUnitPrice;
        }

        public String getMemo() {
            return memo;
        }

        public void setMemo(String memo) {
            this.memo = memo;
        }

        public String getMobile() {
            return mobile;
        }

        public void setMobile(String mobile) {
            this.mobile = mobile;
        }

        public Boolean getNeedPrint() {
            return needPrint;
        }

        public void setNeedPrint(Boolean needPrint) {
            this.needPrint = needPrint;
        }

        public String getBillId() {
            return billId;
        }

        public void setBillId(String billId) {
            this.billId = billId;
        }

        public List<BillFormItem> getItemList() {
            return itemList;
        }

        public void setItemList(List<BillFormItem> itemList) {
            this.itemList = itemList;
        }

        public String getCustomerName() {
            return customerName;
        }

        public void setCustomerName(String customerName) {
            this.customerName = customerName;
        }

        public String getVillageId() {
            return villageId;
        }

        public void setVillageId(String villageId) {
            this.villageId = villageId;
        }

        public Double getPayables() {
            return payables;
        }

        public void setPayables(Double payables) {
            this.payables = payables;
        }

        public Double getRealPayables() {
            return realPayables;
        }

        public void setRealPayables(Double realPayables) {
            this.realPayables = realPayables;
        }
    }

    public static class BillFormItem {

        private String itemId;
        private String goodsId;
        private Double payables;
        private Boolean isReturn = Boolean.FALSE; // 是否退货
        private String storehouseId;
        private int number = 1;
        private String memo;

        public String getStorehouseId() {
            return storehouseId;
        }

        public void setStorehouseId(String storehouseId) {
            this.storehouseId = storehouseId;
        }

        public String getMemo() {
            return memo;
        }

        public void setMemo(String memo) {
            this.memo = memo;
        }

        public int getNumber() {
            return number;
        }

        public void setNumber(int number) {
            this.number = number;
        }

        public String getItemId() {
            return itemId;
        }

        public void setItemId(String itemId) {
            this.itemId = itemId;
        }

        public Boolean getIsReturn() {
            return isReturn;
        }

        public void setIsReturn(Boolean isReturn) {
            this.isReturn = isReturn;
        }

        public String getGoodsId() {
            return goodsId;
        }

        public void setGoodsId(String goodsId) {
            this.goodsId = goodsId;
        }

        public Double getPayables() {
            return payables;
        }

        public void setPayables(Double payables) {
            this.payables = payables;
        }
    }

    public static class GoodsVO extends Goods {

        /**
         *
         */
        private static final long serialVersionUID = -1092928765097409802L;

        private Brand brand;
        private Category category;
        private int inventoryCount = 0;
        private List<GoodsPropValue> propValues;

        public List<GoodsPropValue> getPropValues() {
            return propValues;
        }

        public void setPropValues(List<GoodsPropValue> propValues) {
            this.propValues = propValues;
        }

        public Brand getBrand() {
            return brand;
        }

        public void setBrand(Brand brand) {
            this.brand = brand;
        }

        public Category getCategory() {
            return category;
        }

        public void setCategory(Category category) {
            this.category = category;
        }

        public int getInventoryCount() {
            return inventoryCount;
        }

        public void setInventoryCount(int inventoryCount) {
            this.inventoryCount = inventoryCount;
        }
    }

    /**
     * @author aroot
     */
    public static class VillageVO {

        private Town town;

        private Village village;

        public Village getVillage() {
            return village;
        }

        public void setVillage(Village village) {
            this.village = village;
        }

        public Town getTown() {
            return town;
        }

        public void setTown(Town town) {
            this.town = town;
        }
    }

    public static class VillageVOArray {

        private Town town;

        private List<Village> villageList;

        public Town getTown() {
            return town;
        }

        public void setTown(Town town) {
            this.town = town;
        }

        public List<Village> getVillageList() {
            return villageList;
        }

        public void setVillageList(List<Village> villageList) {
            this.villageList = villageList;
        }
    }

    public static class BillVO implements java.io.Serializable {
        /**
         *
         */
        private static final long serialVersionUID = 464052090380204614L;

        private String id;
        private String villageId;
        private String customerId;
        private Date addTime;
        private Double payables; // 应付账款
        private Double realPayables; // 实付账款
        private Double cost; // 成本
        private Town town;
        private Village village;
        private Customer customer;
        private List<BillVOItem> itemList;
        private String memo;
        private Boolean isChecked = Boolean.FALSE; // 判断是否已经结账
        private Boolean isReturn = Boolean.FALSE; // 判断是否已经结账

        public Boolean getIsReturn() {
            return isReturn;
        }

        public void setIsReturn(Boolean isReturn) {
            this.isReturn = isReturn;
        }

        public Boolean getIsChecked() {
            return isChecked;
        }

        public void setIsChecked(Boolean isChecked) {
            this.isChecked = isChecked;
        }

        public String getMemo() {
            return memo;
        }

        public void setMemo(String memo) {
            this.memo = memo;
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getVillageId() {
            return villageId;
        }

        public void setVillageId(String villageId) {
            this.villageId = villageId;
        }

        public String getCustomerId() {
            return customerId;
        }

        public void setCustomerId(String customerId) {
            this.customerId = customerId;
        }

        public Date getAddTime() {
            return addTime;
        }

        public void setAddTime(Date addTime) {
            this.addTime = addTime;
        }

        public Double getPayables() {
            return payables;
        }

        public void setPayables(Double payables) {
            this.payables = payables;
        }

        public Double getRealPayables() {
            return realPayables;
        }

        public void setRealPayables(Double realPayables) {
            this.realPayables = realPayables;
        }

        public Double getCost() {
            return cost;
        }

        public void setCost(Double cost) {
            this.cost = cost;
        }

        public Town getTown() {
            return town;
        }

        public void setTown(Town town) {
            this.town = town;
        }

        public Village getVillage() {
            return village;
        }

        public void setVillage(Village village) {
            this.village = village;
        }

        public Customer getCustomer() {
            return customer;
        }

        public void setCustomer(Customer customer) {
            this.customer = customer;
        }

        public List<BillVOItem> getItemList() {
            return itemList;
        }

        public void setItemList(List<BillVOItem> itemList) {
            this.itemList = itemList;
        }

        public static class BillVOItem {

            private String billId;
            private Item item;
            private Goods goods;
            private Brand brand;
            private Category category;
            private Double payables;
            private Boolean isReturn;
            private Integer number;

            public Integer getNumber() {
                return number;
            }

            public void setNumber(Integer number) {
                this.number = number;
            }

            public Boolean getIsReturn() {
                if (number == null || number.intValue() == 0) {
                    return true;
                }
                return isReturn;
            }

            public void setIsReturn(Boolean isReturn) {
                this.isReturn = isReturn;
            }

            public Item getItem() {
                return item;
            }

            public void setItem(Item item) {
                this.item = item;
            }

            public String getBillId() {
                return billId;
            }

            public void setBillId(String billId) {
                this.billId = billId;
            }

            public Goods getGoods() {
                return goods;
            }

            public void setGoods(Goods goods) {
                this.goods = goods;
            }

            public Brand getBrand() {
                return brand;
            }

            public void setBrand(Brand brand) {
                this.brand = brand;
            }

            public Category getCategory() {
                return category;
            }

            public void setCategory(Category category) {
                this.category = category;
            }

            public Double getPayables() {
                return payables;
            }

            public void setPayables(Double payables) {
                this.payables = payables;
            }
        }
    }

}
